<template>
  <div class="containers">
    <div class="canvas" ref="canvas"></div>
     <ul class="buttons">
      <li>
        <a href="javascript:" @click="$refs.refFile.click()">加载本地BPMN文件</a>
        <input type="file" id="files" ref="refFile" style="display: none" @change="loadXML" />
      </li>
      <li>
        <a href="javascript:" ref="saveXML" title="保存为bpmn">保存为BPMN文件</a>
      </li>
      <li>
        <a href="javascript:" ref="saveSvg" title="保存为svg">保存为SVG图片</a>
      </li>
      <li>
        <a href="javascript:" class="active" @click="handlerUndo" title="撤销操作">撤销</a>
      </li>
      <li>
        <a href="javascript:" class="active" @click="handlerRedo" title="恢复操作">恢复</a>
      </li>
      <li>
        <a href="javascript:" class="active" @click="handlerZoom(0.1)" title="放大">放大</a>
      </li>
      <li>
        <a href="javascript:" class="active" @click="handlerZoom(-0.1)" title="缩小">缩小</a>
      </li>
      <li>
        <a href="javascript:" class="active" @click="handlerZoom(0)" title="还原">还原</a>
      </li>
    </ul>
  </div>
</template>

<script>
// 引入相关的依赖
import BpmnModeler from 'bpmn-js/lib/Modeler'
import {
  xmlStr
} from './mock/xmlStr' // 这里是直接引用了xml字符串
export default {
  name: 'main-content',
  mounted() {
    this.init();
  },
  data() {
    return {
      bpmnModeler: null,
      container: null,
      canvas: null,
      scale: 1.0,
      xmlStr
    };
  },
  methods: {
    init() {
      const canvas = this.$refs.canvas;
      this.bpmnModeler = new BpmnModeler({
        container: canvas,
        keyboard: {
          // ctrl + z : 撤销
          // ctrl + y : 恢复
          // ctrl + c : 复制
          // ctrl + v : 粘贴
          // ctrl + + : 放大
          // ctrl + - : 缩小
          // ctrl + 0 : 恢复
          // ctrl + del : 删除
          // ctrl + 箭头 : 上下左右移动
          // 除了键盘快捷键外，bpmn-js也支持ctrl+鼠标滚轮来控制放大缩小
          bindTo: window
        }
      });
      this.createNewDiagram();
    },
    // 创建一个新的图层
    async createNewDiagram() {
      try {
        const result = await this.bpmnModeler.importXML(this.xmlStr);
        const { warnings } = result;
        console.log(warnings);
        this.success();
      } catch (err) {
        console.log(err.message, err.warnings);
      }
    },
    success() {
      this.addBpmnListener();
      this.addEventBusListener();
    },
    // 加载本地bpmn文件
    async loadXML() {
      const that = this;
      const file = this.$refs.refFile.files[0];
      const reader = new FileReader();
      reader.readAsText(file);
      reader.onload = function() {
        that.xmlStr = this.result;
        that.createNewDiagram();
      };
    },
    // 创建监听
    async addBpmnListener() {
      const that = this;
      const downloadLink = this.$refs.saveXML;
      const downloadSvgLink = this.$refs.saveSvg;
      async function handleResult() {
        try {
          const result = await that.saveSVG();
          const { svg } = result;
          that.setEncoded(downloadSvgLink, 'sample.svg', svg);
        } catch (err) {
          console.log(err);
        }
        try {
          const result = await that.saveXML();
          const { xml } = result;
          that.setEncoded(downloadLink, 'sample.bpmn', xml);
        } catch (err) {
          console.log(err);
        }
      }
      handleResult();
      this.bpmnModeler.on('commandStack.changed', handleResult);
    },
    // eventbug监听
    addEventBusListener() {
      const that = this;
      const eventBus = this.bpmnModeler.get('eventBus');
      eventBus.on('element.click', function(e) {
        that.elementClick(e);
      });
    },
    // 节点点击事件
    elementClick(e) {
      if (e.element.businessObject.$type === 'bpmn:UserTask') {
        console.log(
          '这是一个用户节点',
          e.element.businessObject.id,
          e.element.businessObject.$type,
          e.element.businessObject.name
        );
      }
    },
    // 保存成svg文件
    async saveSVG(done) {
      try {
        const result = await this.bpmnModeler.saveSVG(done);
        return result;
      } catch (err) {
        console.log(err);
      }
    },
    // 保存成bpmn文件
    async saveXML(done) {
      try {
        const result = await this.bpmnModeler.saveXML({ format: true }, done);
        return result;
      } catch (err) {
        console.log(err);
      }
    },
    // 设置编码格式
    setEncoded(link, name, data) {
      const encodedData = encodeURIComponent(data);
      if (data) {
        link.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData;
        link.download = name;
      }
    },
    // 恢复
    handlerRedo() {
      this.bpmnModeler.get('commandStack').redo();
    },
    // 撤销
    handlerUndo() {
      this.bpmnModeler.get('commandStack').undo();
    },
    // 缩放
    handlerZoom(radio) {
      const newScale = !radio ? 1.0 : this.scale + radio;
      this.bpmnModeler.get('canvas').zoom(newScale);
      this.scale = newScale;
    }
  }
}
</script>

<style scoped>
.containers{
  position: absolute;
  background-color: #ffffff;
  width: 100%;
  height: 100%;
}
.canvas{
  width: 100%;
  height: 100%;
}
.panel{
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
}
.containers {
  background: white;
  overflow: auto;
  background-image: linear-gradient(
      90deg,
      rgba(220, 220, 220, 0.5) 6%,
      transparent 0
    ),
    linear-gradient(rgba(192, 192, 192, 0.5) 6%, transparent 0);
  background-size: 12px 12px;
  width: 100%;
  height: calc(100vh - 82px);
  -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
}
.buttons {
  position: absolute;
  left: 20px;
  bottom: 20px;
}
.buttons li {
  display: inline-block;
  margin: 5px;
}
.buttons li a {
  color: #333;
  background: #fff;
  cursor: pointer;
  padding: 8px;
  border: 1px solid #ccc;
  text-decoration: none;
}
</style>
